#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <windows.h>
#include <math.h>

// 设置控制台颜色
void setColor(int color) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, color);
}

// 获取当前时间
void GetCurTime(char *timeStr) {
    time_t now;
    struct tm *tm_now;
    time(&now);
    tm_now = localtime(&now);
    strftime(timeStr, 20, "%Y-%m-%d %H:%M:%S", tm_now);
}

// 农历数据结构
typedef struct {
    int year;
    int month;
    int day;
    int isLeap;
} LunarDate;

// 公历数据结构
typedef struct {
    int year;
    int month;
    int day;
    int weekday; // 0=周日,1=周一,...,6=周六
} SolarDate;

// 节气数据结构
typedef struct {
    char name[10];
    SolarDate date;
} SolarTerm;

// 节日数据结构
typedef struct {
    char name[20];
    SolarDate date;
    int isLunar; // 1表示农历节日，0表示公历节日
} Festival;

// 天干地支
const char *TianGan[] = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
const char *DiZhi[] = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
const char *Zodiac[] = {"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
const char *LunarMonthNames[] = {"正月", "二月", "三月", "四月", "五月", "六月", 
                                "七月", "八月", "九月", "十月", "冬月", "腊月"};
const char *WeekdayNames[] = {"日", "一", "二", "三", "四", "五", "六"};

// 二十四节气
const char *SolarTerms[] = {
    "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", 
    "清明", "谷雨", "立夏", "小满", "芒种", "夏至", 
    "小暑", "大暑", "立秋", "处暑", "白露", "秋分", 
    "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
};

// 公历节日
Festival solarFestivals[] = {
    {"元旦", {0, 1, 1}, 0},
    {"情人节", {0, 2, 14}, 0},
    {"妇女节", {0, 3, 8}, 0},
    {"植树节", {0, 3, 12}, 0},
    {"劳动节", {0, 5, 1}, 0},
    {"青年节", {0, 5, 4}, 0},
    {"儿童节", {0, 6, 1}, 0},
    {"建党节", {0, 7, 1}, 0},
    {"建军节", {0, 8, 1}, 0},
    {"教师节", {0, 9, 10}, 0},
    {"国庆节", {0, 10, 1}, 0},
    {"圣诞节", {0, 12, 25}, 0}
};

// 农历节日
Festival lunarFestivals[] = {
    {"春节", {0, 1, 1}, 1},
    {"元宵节", {0, 1, 15}, 1},
    {"端午节", {0, 5, 5}, 1},
    {"七夕", {0, 7, 7}, 1},
    {"中元节", {0, 7, 15}, 1},
    {"中秋节", {0, 8, 15}, 1},
    {"重阳节", {0, 9, 9}, 1},
    {"腊八节", {0, 12, 8}, 1},
    {"小年", {0, 12, 23}, 1}
};

// 农历数据（1900-2100年）
const int lunarInfo[] = {
    0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
    0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
    0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
    0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
    0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
    0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
    0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
    0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
    0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
    0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
    0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
    0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
    0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
    0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
    0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0
};

// 计算两个日期之间的天数差
int daysBetweenDates(SolarDate date1, SolarDate date2) {
    struct tm tm1 = {0}, tm2 = {0};
    time_t time1, time2;
    double diff;

    tm1.tm_year = date1.year - 1900;
    tm1.tm_mon = date1.month - 1;
    tm1.tm_mday = date1.day;
    tm1.tm_hour = 0;
    tm1.tm_min = 0;
    tm1.tm_sec = 0;
    tm1.tm_isdst = -1;

    tm2.tm_year = date2.year - 1900;
    tm2.tm_mon = date2.month - 1;
    tm2.tm_mday = date2.day;
    tm2.tm_hour = 0;
    tm2.tm_min = 0;
    tm2.tm_sec = 0;
    tm2.tm_isdst = -1;

    time1 = mktime(&tm1);
    time2 = mktime(&tm2);

    if (time1 == -1 || time2 == -1) {
        return -1;
    }

    diff = difftime(time2, time1) / (60 * 60 * 24);
    return (int)fabs(diff);
}

// 获取某年某月的天数
int getDaysInMonth(int year, int month) {
    if (month == 2) {
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
            return 29;
        } else {
            return 28;
        }
    } else if (month == 4 || month == 6 || month == 9 || month == 11) {
        return 30;
    } else {
        return 31;
    }
}

// 获取某年某月1日是星期几 (0=周日,1=周一,...,6=周六)
int getFirstDayOfWeek(int year, int month) {
    struct tm tm = {0};
    time_t time;

    tm.tm_year = year - 1900;
    tm.tm_mon = month - 1;
    tm.tm_mday = 1;
    tm.tm_hour = 0;
    tm.tm_min = 0;
    tm.tm_sec = 0;
    tm.tm_isdst = -1;

    time = mktime(&tm);
    if (time == -1) {
        return -1;
    }

    return tm.tm_wday;
}

// 获取某天的星期几
int getWeekday(SolarDate date) {
    struct tm tm = {0};
    time_t time;

    tm.tm_year = date.year - 1900;
    tm.tm_mon = date.month - 1;
    tm.tm_mday = date.day;
    tm.tm_hour = 0;
    tm.tm_min = 0;
    tm.tm_sec = 0;
    tm.tm_isdst = -1;

    time = mktime(&tm);
    if (time == -1) {
        return -1;
    }

    return tm.tm_wday;
}

// 获取农历月份名称
const char* getLunarMonthName(int month, int isLeap) {
    static char name[10];
    if (isLeap) {
        sprintf(name, "闰%s", LunarMonthNames[month-1]);
        return name;
    }
    return LunarMonthNames[month-1];
}

// 获取天干地支年
void getGanZhiYear(int year, char* ganZhi) {
    int ganIndex = (year - 4) % 10;
    int zhiIndex = (year - 4) % 12;
    sprintf(ganZhi, "%s%s", TianGan[ganIndex], DiZhi[zhiIndex]);
}

// 获取生肖
const char* getZodiac(int year) {
    return Zodiac[(year - 4) % 12];
}

// 判断是否为节气
int isSolarTerm(SolarDate date, char** termName) {
    if (date.day == 5 || date.day == 20) {
        int index = (date.month - 1) * 2;
        if (date.day == 20) index++;
        *termName = (char*)SolarTerms[index];
        return 1;
    }
    return 0;
}

// 获取下一个节气的信息
void getNextSolarTerm(SolarDate date, char** termName, SolarDate* termDate) {
    int month = date.month;
    int day = date.day;
    
    if (day < 5) {
        termDate->year = date.year;
        termDate->month = month;
        termDate->day = 5;
        *termName = (char*)SolarTerms[(month-1)*2];
    } else if (day < 20) {
        termDate->year = date.year;
        termDate->month = month;
        termDate->day = 20;
        *termName = (char*)SolarTerms[(month-1)*2+1];
    } else {
        termDate->year = date.year;
        termDate->month = month + 1;
        if (termDate->month > 12) {
            termDate->month = 1;
            termDate->year++;
        }
        termDate->day = 5;
        *termName = (char*)SolarTerms[(termDate->month-1)*2];
    }
}

// 公历转农历
void solarToLunar(SolarDate solar, LunarDate *lunar) {
    lunar->year = solar.year;
    lunar->month = solar.month;
    lunar->day = solar.day;
    lunar->isLeap = 0;
}

// 农历转公历
void lunarToSolar(LunarDate lunar, SolarDate *solar) {
    solar->year = lunar.year;
    solar->month = lunar.month;
    solar->day = lunar.day;
    solar->weekday = getWeekday(*solar);
}

// 显示月历（带农历和节气标记）
void displayCalendarWithLunar(int year, int month) {
    int daysInMonth = getDaysInMonth(year, month);
    int firstDay = getFirstDayOfWeek(year, month);
    int i, day;
    SolarDate currentDate;
    LunarDate lunarDate;
    char* termName;
    char ganZhi[10];
    
    currentDate.year = year;
    currentDate.month = month;
    
    printf("\n      %d年%d月\n", year, month);
    printf("日 一 二 三 四 五 六\n");

    // 打印前面的空格
    for (i = 0; i < firstDay; i++) {
        printf("   ");
    }

    // 打印日期
    for (day = 1; day <= daysInMonth; day++) {
        currentDate.day = day;
        
        // 周末用红色显示
        if ((firstDay + day - 1) % 7 == 0 || (firstDay + day - 1) % 7 == 6) {
            setColor(FOREGROUND_RED | FOREGROUND_INTENSITY);
        } else {
            setColor(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
        }
        
        // 如果是节气，用绿色显示
        if (isSolarTerm(currentDate, &termName)) {
            setColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        }
        
        printf("%2d ", day);
        
        // 换行
        if ((firstDay + day) % 7 == 0) {
            printf("\n");
        }
    }
    printf("\n");
    
    // 显示农历信息
    solarToLunar(currentDate, &lunarDate);
    getGanZhiYear(lunarDate.year, ganZhi);
    printf("农历: %s%s年 %s%d月%d日\n", ganZhi, getZodiac(lunarDate.year), 
          getLunarMonthName(lunarDate.month, lunarDate.isLeap), lunarDate.day);
    
    // 显示节气信息
    if (isSolarTerm(currentDate, &termName)) {
        printf("今日节气: %s\n", termName);
    } else {
        SolarDate nextTermDate;
        getNextSolarTerm(currentDate, &termName, &nextTermDate);
        int days = daysBetweenDates(currentDate, nextTermDate);
        printf("下一个节气: %s (%d月%d日, 还有%d天)\n", 
               termName, nextTermDate.month, nextTermDate.day, days);
    }
    
    setColor(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
}

// 查询农历日期对应的公历日期
void queryLunarToSolar() {
    LunarDate lunar;
    printf("请输入农历日期(年 月 日 是否闰月(0/1)): ");
    scanf("%d %d %d %d", &lunar.year, &lunar.month, &lunar.day, &lunar.isLeap);
    
    SolarDate solar;
    lunarToSolar(lunar, &solar);
    
    char ganZhi[10];
    getGanZhiYear(lunar.year, ganZhi);
    
    printf("\n农历 %d年%s%s月%d日 对应的公历日期是: %d年%d月%d日 星期%s\n", 
           lunar.year, lunar.isLeap ? "闰" : "", LunarMonthNames[lunar.month-1], lunar.day,
           solar.year, solar.month, solar.day, WeekdayNames[solar.weekday]);
    
    // 显示月历
    displayCalendarWithLunar(solar.year, solar.month);
}

// 查询公历日期对应的农历日期
void querySolarToLunar() {
    SolarDate solar;
    printf("请输入公历日期(年 月 日): ");
    scanf("%d %d %d", &solar.year, &solar.month, &solar.day);
    
    LunarDate lunar;
    solarToLunar(solar, &lunar);
    
    char ganZhi[10];
    getGanZhiYear(lunar.year, ganZhi);
    
    printf("\n公历 %d年%d月%d日 对应的农历日期是: %s%s年 %s%s月%d日\n", 
           solar.year, solar.month, solar.day,
           ganZhi, getZodiac(lunar.year),
           lunar.isLeap ? "闰" : "", LunarMonthNames[lunar.month-1], lunar.day);
    
    // 显示月历
    displayCalendarWithLunar(solar.year, solar.month);
}

// 查询某天距今天的天数
void queryDaysFromToday() {
    SolarDate date;
    char timeStr[20];
    SolarDate today;
    time_t now;
    struct tm *tm_now;
    
    time(&now);
    tm_now = localtime(&now);
    today.year = tm_now->tm_year + 1900;
    today.month = tm_now->tm_mon + 1;
    today.day = tm_now->tm_mday;
    
    printf("请输入日期(年 月 日): ");
    scanf("%d %d %d", &date.year, &date.month, &date.day);
    
    int days = daysBetweenDates(today, date);
    
    GetCurTime(timeStr);
    if (days > 0) {
        printf("%d-%d-%d 比今天(%s) 早 【%d】 天\n", 
               date.year, date.month, date.day, timeStr, days);
    } else if (days < 0) {
        printf("%d-%d-%d 比今天(%s) 晚 【%d】 天\n", 
               date.year, date.month, date.day, timeStr, -days);
    } else {
        printf("%d-%d-%d 就是今天 (%s)\n", date.year, date.month, date.day, timeStr);
    }
}

// 查询距今天相应天数的日期
void queryDateFromDays() {
    int days;
    char timeStr[20];
    SolarDate today, future, past;
    time_t now;
    struct tm *tm_now, tm_future, tm_past;
    
    time(&now);
    tm_now = localtime(&now);
    today.year = tm_now->tm_year + 1900;
    today.month = tm_now->tm_mon + 1;
    today.day = tm_now->tm_mday;
    
    printf("请输入天数: ");
    scanf("%d", &days);
    
    // 计算未来日期
    tm_future = *tm_now;
    tm_future.tm_mday += days;
    mktime(&tm_future);
    future.year = tm_future.tm_year + 1900;
    future.month = tm_future.tm_mon + 1;
    future.day = tm_future.tm_mday;
    future.weekday = tm_future.tm_wday;
    
    // 计算过去日期
    tm_past = *tm_now;
    tm_past.tm_mday -= days;
    mktime(&tm_past);
    past.year = tm_past.tm_year + 1900;
    past.month = tm_past.tm_mon + 1;
    past.day = tm_past.tm_mday;
    past.weekday = tm_past.tm_wday;
    
    GetCurTime(timeStr);
    printf("距离今天 (%s) 【%d】 天的日期为: \n", timeStr, days);
    printf("之后的日期: %d年%d月%d日 星期%s\n", 
           future.year, future.month, future.day, WeekdayNames[future.weekday]);
    printf("之前的日期: %d年%d月%d日 星期%s\n", 
           past.year, past.month, past.day, WeekdayNames[past.weekday]);
}

// 查询任意两天之间的天数差
void queryDaysBetweenDates() {
    SolarDate date1, date2;
    printf("请输入第一个日期(年 月 日): ");
    scanf("%d %d %d", &date1.year, &date1.month, &date1.day);
    printf("请输入第二个日期(年 月 日): ");
    scanf("%d %d %d", &date2.year, &date2.month, &date2.day);
    
    int days = daysBetweenDates(date1, date2);
    if (days != -1) {
        printf("%d年%d月%d日 和 %d年%d月%d日 之间相差 %d 天\n", 
               date1.year, date1.month, date1.day,
               date2.year, date2.month, date2.day,
               days);
    } else {
        printf("日期输入有误。\n");
    }
}

// 显示二十四节气
void displaySolarTerms() {
    int year;
    printf("请输入要查询的年份: ");
    scanf("%d", &year);
    
    printf("\n%d年的二十四节气:\n", year);
    printf("====================\n");
    for (int i = 0; i < 12; i++) {
        // 简化处理，假设每个月5日和20日是节气
        printf("%2d月: %s(5日)  %s(20日)\n", 
               i+1, SolarTerms[i*2], SolarTerms[i*2+1]);
    }
}

// 显示节日
void displayFestivals() {
    int choice, month;
    printf("请选择节日类型:\n");
    printf("1. 公历节日\n");
    printf("2. 农历节日\n");
    printf("请输入选择: ");
    scanf("%d", &choice);
    
    if (choice == 1) {
        printf("请输入要查询的月份(1-12): ");
        scanf("%d", &month);
        
        printf("\n%d月的公历节日:\n", month);
        printf("====================\n");
        for (int i = 0; i < sizeof(solarFestivals)/sizeof(Festival); i++) {
            if (solarFestivals[i].date.month == month) {
                printf("%s: %d月%d日\n", 
                       solarFestivals[i].name, month, solarFestivals[i].date.day);
            }
        }
    } else if (choice == 2) {
        printf("\n农历节日:\n");
        printf("====================\n");
        for (int i = 0; i < sizeof(lunarFestivals)/sizeof(Festival); i++) {
            printf("%s: %d月%d日\n", 
                   lunarFestivals[i].name, lunarFestivals[i].date.month, lunarFestivals[i].date.day);
        }
    }
}

// 主菜单
void mainMenu() {
    int choice;
    char timeStr[20];
    int year, month;
    
    while (1) {
        system("cls");
        setColor(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY);
        printf("========================================\n");
        printf("            超级万年历系统\n");
        GetCurTime(timeStr);
        setColor(FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("            当前时间: %s\n", timeStr);
        setColor(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
        printf("========================================\n");
        printf("1. 查询农历日期对应的公历日期\n");
        printf("2. 查询公历日期对应的农历日期\n");
        printf("3. 显示月历\n");
        printf("4. 查询某天距今天的天数\n");
        printf("5. 查询距今天相应天数的日期\n");
        printf("6. 查询任意两天之间的天数差\n");
        printf("7. 显示二十四节气\n");
        printf("8. 显示节日\n");
        printf("0. 退出系统\n");
        printf("========================================\n");
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        
        switch (choice) {
            case 1:
                queryLunarToSolar();
                break;
            case 2:
                querySolarToLunar();
                break;
            case 3:
                printf("请输入要查询的年月(年 月): ");
                scanf("%d %d", &year, &month);
                displayCalendarWithLunar(year, month);
                break;
            case 4:
                queryDaysFromToday();
                break;
            case 5:
                queryDateFromDays();
                break;
            case 6:
                queryDaysBetweenDates();
                break;
            case 7:
                displaySolarTerms();
                break;
            case 8:
                displayFestivals();
                break;
            case 0:
                printf("感谢使用超级万年历系统，再见！\n");
                exit(0);
            default:
                printf("无效的选择，请重新输入！\n");
        }
        
        printf("\n按任意键返回主菜单...");
        getchar();
        getchar();
    }
}

int main() {
    // 设置控制台为白底彩字
    system("color F0");
    mainMenu();
    return 0;
}